﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace LanderWpf
{
    public enum SurfaceType
    {
        Smooth,
        Rock
    }

    public enum FlightStatus
    {
        Flying,
        Landed,
        Crashed
    }

    public class Lander : INotifyPropertyChanged
    {
        #region Properties

        public int Pitch      { get; private set; }
        public int Roll       { get; private set; }
        public int Altitude   { get; private set; }
        public int Lattitude  { get; private set; }
        public int Longitude  { get; private set; }
        public int Fuel       { get; private set; }

        public FlightStatus Status { get; private set; }

        public SurfaceType[,] Surface { get; private set; }

        public SurfaceType Below
        {
            get
            {
                return Surface[Lattitude, Longitude];
            }
        }

        private Random rng;

        #endregion

        #region Constructor

        public Lander()
        {
            rng = new Random();

            CreateSurface(10);

            Pitch = rng.Next(0, 360);
            Roll = rng.Next(0, 360);

            Altitude = 20;
            Lattitude = rng.Next(Surface.GetLength(1));
            Longitude = rng.Next(Surface.GetLength(0));
            
            Fuel = 50;

            Status = FlightStatus.Flying;
        }

        public void CreateSurface(int size)
        {
            Surface = new SurfaceType[size, size];
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    Surface[i, j] = SurfaceType.Rock;
                }
            }

            // always generate 4 landing spots
            for (int n = 0; n < 4; n++)
            {
                int i, j;
                do
                {
                    i = rng.Next(10);
                    j = rng.Next(10);
                } while (Surface[i, j] == SurfaceType.Smooth);

                Surface[i, j] = SurfaceType.Smooth;
            }
        }

        #endregion

        #region Manuevering Methods

        public void PitchFore()
        {
            if (Status == FlightStatus.Flying)
            {
                int r = rng.Next(5, 11);
                Pitch += r;
                while (Pitch < 0) Pitch += 360;
                while (Pitch >= 360) Pitch -= 360;
                Fuel -= 1;

                Changed("Pitch");
                Changed("Fuel");

                Check();
            }
        }

        public void PitchAft()
        {
            if (Status == FlightStatus.Flying)
            {
                int r = rng.Next(5, 11);
                Pitch -= r;
                while (Pitch < 0) Pitch += 360;
                while (Pitch >= 360) Pitch -= 360;
                Fuel -= 1;

                Changed("Pitch");
                Changed("Fuel");

                Check();
            }
        }

        public void RollLeft()
        {
            if (Status == FlightStatus.Flying)
            {
                int r = rng.Next(5, 11);
                Roll += r;
                while (Roll < 0) Roll += 360;
                while (Roll >= 360) Roll -= 360;
                Fuel -= 1;

                Changed("Roll");
                Changed("Fuel");

                Check();
            }
        }

        public void RollRight()
        {
            if (Status == FlightStatus.Flying)
            {
                int r = rng.Next(5, 11);
                Roll -= r;
                while (Roll < 0) Roll += 360;
                while (Roll >= 360) Roll -= 360;
                Fuel -= 1;

                Changed("Roll");
                Changed("Fuel");

                Check();
            }
        }

        public void Ascend()
        {
            if (Status == FlightStatus.Flying)
            {
                int r = rng.Next(1, 6);
                Altitude += r;
                Fuel -= 1;

                Changed("Altitude");
                Changed("Fuel");

                Check();
            }
        }

        public void Descend()
        {
            if (Status == FlightStatus.Flying)
            {
                int r = rng.Next(1, 6);
                Altitude -= r;
                if (Altitude < 0) Altitude = 0;

                Changed("Altitude");

                Check();
            }
        }

        public void SurgeFore()
        {
            if (Status == FlightStatus.Flying)
            {
                Lattitude += 1;
                while (Lattitude < 0) Lattitude += Surface.GetLength(0);
                while (Lattitude >= Surface.GetLength(0)) Lattitude -= Surface.GetLength(0);
                Fuel -= 1;

                Changed("Lattitude");
                Changed("Fuel");
                Changed("Below");

                Check();
            }
        }

        public void SurgeAft()
        {
            if (Status == FlightStatus.Flying)
            {
                Lattitude -= 1;
                while (Lattitude < 0) Lattitude += Surface.GetLength(0);
                while (Lattitude >= Surface.GetLength(0)) Lattitude -= Surface.GetLength(0);
                Fuel -= 1;

                Changed("Lattitude");
                Changed("Fuel");
                Changed("Below");

                Check();
            }
        }

        public void SwayLeft()
        {
            if (Status == FlightStatus.Flying)
            {
                Longitude += 1;
                while (Longitude < 0) Longitude += Surface.GetLength(1);
                while (Longitude >= Surface.GetLength(1)) Longitude -= Surface.GetLength(1);
                Fuel -= 1;

                Changed("Longitude");
                Changed("Fuel");
                Changed("Below");

                Check();
            }
        }

        public void SwayRight()
        {
            if (Status == FlightStatus.Flying)
            {
                Longitude -= 1;
                while (Longitude < 0) Longitude += Surface.GetLength(1);
                while (Longitude >= Surface.GetLength(1)) Longitude -= Surface.GetLength(1);
                Fuel -= 1;

                Changed("Longitude");
                Changed("Fuel");
                Changed("Below");

                Check();
            }
        }

        #endregion

        #region Check Method

        public void Check()
        {
            if (Status == FlightStatus.Flying)
            {
                if (Fuel <= 0)
                {
                    Status = FlightStatus.Crashed;
                    Changed("Status");
                }
                else if (Altitude <= 0)
                {
                    if ((Pitch <= 10 || Pitch >= 350) &&
                        (Roll <= 10 || Roll >= 350) &&
                        Surface[Lattitude, Longitude] == SurfaceType.Smooth)
                    {
                        Status = FlightStatus.Landed;
                        Changed("Status");
                    }
                    else
                    {
                        Status = FlightStatus.Crashed;
                        Changed("Status");
                    }
                }
            }
        }

        #endregion

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        public void Changed(string property)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(property));
        }

        #endregion
    }
}
